// 1. 在选中的目录下创建文件夹，创建文件
// 2. 在文件夹下填入内容
// 3. 在文件夹下执行命令
package main

import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"strings"
	"sync"
	"time"
)

var fItems = []folderItem{
	{
		isfolder: true,
		name:     "测试1",
		command:  "go mod init project",
		content:  "",
		folderItems: []folderItem{
			{
				isfolder:    true,
				name:        "测试11",
				command:     "",
				content:     "",
				folderItems: nil,
			},
		},
	},
	{
		isfolder:    true,
		name:        "测试2",
		command:     "",
		content:     "",
		folderItems: nil,
	}, {
		isfolder:    false,
		name:        "测试3.txt",
		command:     "",
		content:     "测试文本",
		folderItems: nil,
	},
}

var fInfo = folderInfo{command: "", folderItems: fItems}

var wg = &sync.WaitGroup{}

// TODO:json字符串 采用从文件中获取
// TODO:采用cli实现命令行工具
// TODO:实现go标准文件
// TODO:vue标准文件构建
func main() {
	log.Println("创建开始")
	now := time.Now()

	path := "D:\\yyt"
	rootPath := filepath.Join(path, "test")
	if fInfo.folderItems != nil {

		for _, info := range fInfo.folderItems {
			// 	wg.Add(1)

			// 	go func(info folderItem) {
			msg, _ := createFolder(rootPath, info)
			log.Println(msg)
			// 		wg.Done()
			// 	}(info)
		}
	}

	wg.Wait()
	sp := time.Since(now).Seconds()
	log.Printf("创建结束,运行时间：%fs", sp)
}

// 创建文件夹
func createFolder(rootPath string, finfo folderItem) (msg string, err error) {
	// 设定根目录
	os.Chdir(rootPath)

	fPath := path.Join(rootPath, finfo.name)
	if !finfo.isfolder {
		return createFile(rootPath, finfo)
	}

	// 判断是否存在
	if boo, _ := PathExists(fPath); boo {
		msg = fmt.Sprintf("【%-10s】，文件名：%s，路径：%s\n", "文件夹已经存在", finfo.name, fPath)
		return msg, nil
	}

	err = os.MkdirAll(finfo.name, 0777)
	if err != nil {
		msg = fmt.Sprintf("【%-10s】err:%v\n", "创建文件夹异常", err.Error())
		return msg, nil
	}

	// 执行命令
	if !strings.EqualFold(finfo.command, "") {
		msg, _ := runCommand(fPath, finfo.command)
		log.Println(msg)
	}

	msg = fmt.Sprintf("【%-10s】，文件名：%s，路径：%s\n", "创建文件夹成功", finfo.name, fPath)
	// 判断是否有子目录
	if finfo.folderItems != nil {
		rootPath := filepath.Join(rootPath, finfo.name)
		for _, v := range finfo.folderItems {
			somMsg, _ := createFolder(rootPath, v)
			msg += somMsg
		}
	}

	return msg, err
}

// 创建文件
func createFile(rootPath string, finfo folderItem) (msg string, err error) {
	if finfo.isfolder {
		createFolder(rootPath, finfo)
	}
	fPath := path.Join(rootPath, finfo.name)

	// 判断是否存在
	if boo, _ := PathExists(fPath); boo {
		msg = fmt.Sprintf("【%-10s】，文件名：%s，路径：%s\n", "文件已经存在", finfo.name, fPath)
		return msg, nil
	}

	f, err := os.Create(finfo.name)
	if err != nil {
		msg = fmt.Sprintf("【%-10s】，err:%v\n", "创建文件异常", err.Error())
		return msg, err
	}
	defer f.Close()

	// 执行命令
	if !strings.EqualFold(finfo.command, "") {
		msg, _ := runCommand(fPath, finfo.command)
		log.Println(msg)
	}

	// 写入文件
	if !strings.EqualFold(finfo.content, "") {
		_, err := f.WriteString(finfo.content)
		if err != nil {
			msg = fmt.Sprintf("【%-10s】，文件名：%s，路径：%s，err:%v\n", "写入文件异常", f.Name(), fPath, err.Error())
			return msg, nil
		}
	}

	msg = fmt.Sprintf("【%-10s】，文件名：%s，路径：%s，\n", "创建文件成功", f.Name(), fPath)
	return msg, nil
}

// 执行命令
func runCommand(path string, command string) (msg string, err error) {
	finfoCommand := strings.Split(command, " ")
	commandExec := exec.Command(finfoCommand[0], finfoCommand[1:]...)
	commandExec.Dir = path
	err = commandExec.Run()
	commandResultStr := ""
	if err != nil {
		msg = fmt.Sprintf("【%-10s】，命令：%s，路径：%s，err：%v\n", "执行命令错误", command, path, err.Error())
		return
	}
	out, _ := commandExec.CombinedOutput()
	commandResultStr = string(out)
	msg = fmt.Sprintf("【%-10s】，命令：%s，路径：%s，返回：%s\n", "执行命令成功", command, path, commandResultStr)
	return
}

// 判断文件是否存在
func PathExists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return false, nil
	}
	if os.IsExist(err) {
		return true, nil
	}
	return false, err
}

type folderInfo struct {
	command     string
	folderItems []folderItem
}

type folderItem struct {
	isfolder    bool
	name        string
	command     string
	content     string
	folderItems []folderItem
}
